/*!
 Temelia - Matrix interface.

 Copyright (C) 2008 Ceata (http://cod.ceata.org/proiecte/temelia).

 @author Dascalu Laurentiu

 This program is free software; you can redistribute it and
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 3
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#ifndef MATRIX_H_
#define MATRIX_H_

#include "platform.h"
#include "common.h"

struct _matrix_t;
typedef struct _matrix_t *matrix_t;

/*!
 * @brief Returns an empty matrix
 * Complexity O(1)
 *
 * @param Rows number
 * @param Columns number
 */
DECLSPEC matrix_t matrix_new(int rows, int columns);

/*!
 * @brief Clones given matrix
 * Complexity O(rows * columns)
 *
 * @param Matrix
 */
DECLSPEC matrix_t matrix_clone(matrix_t matrix);

/*!
 * @brief Frees the memory occupied by matrix.
 * Complexity O(1)
 *
 * @param Matrix
 */
DECLSPEC void matrix_delete(matrix_t matrix);

/*!
 * @brief Resizes a matrix, keeping the old matrix alignment.
 * @param Matrix
 * @param Rows number
 * @param Columns number
 */
DECLSPEC void matrix_resize(matrix_t matrix, int rows, int columns);

/*!
 * @brief Returns a zero matrix
 * Complexity O(1)
 *
 * @param Rows
 * @param Columns
 */
DECLSPEC matrix_t matrix_zeros(int rows, int columns);

/*!
 * @brief Sets key value at position in matrix.
 * Complexity O(1)
 *
 * @param Matrix
 * @param Row
 * @param Column
 * @param Key reference
 */
DECLSPEC void matrix_set_key_at(matrix_t matrix, int row, int column, void *key);

/*!
 * @brief Returns key at position in a matrix.
 * Complexity O(1)
 *
 * @param Matrix
 * @param Row
 * @param Column
 */
DECLSPEC void *matrix_get_key_at(matrix_t matrix, int row, int column);

/*!
 * @brief Returns number of rows of matrix.
 * Complexity O(1)
 *
 * @param Matrix
 */
DECLSPEC int matrix_get_rows_number(matrix_t matrix);

/*!
 * @brief Returns number of columns of matrix.
 * Complexity O(1)
 *
 * @param Matrix
 */
DECLSPEC int matrix_get_columns_number(matrix_t matrix);

/*!
 * @brief Returns the internal implementation of matrix.
 * Currently, this data structure is implemented
 * as an array of pointers to void ( void ** ).
 * Complexity O(1)
 *
 * @param Matrix
 */
DECLSPEC void *matrix_get_implementation(matrix_t matrix);

/*!
 * @brief Returns keys from row. You have to free the returned array
 * because of the memory alignment, or you'll have memory leaks.
 * Complexity O(columns)
 *
 * @param Matrix
 * @param Row
 */
DECLSPEC void **matrix_get_row(matrix_t matrix, int row);

/*!
 * @brief Returns keys from row. Free the returned pointer.
 * Complexity O(rows)
 *
 * @param Matrix
 * @param Column
 * @see matrix_get_row
 */
DECLSPEC void **matrix_get_column(matrix_t matrix, int column);

/*!
 * @brief Swaps two rows.
 * Complexity O(columns)
 *
 * @param Matrix
 * @param First row
 * @param Second row
 */
DECLSPEC void matrix_swap_rows(matrix_t matrix, int first_row, int second_row);

/*!
 * @brief Swaps two columns.
 * Complexity O(rows)
 *
 * @param Matrix
 * @param First column
 * @param Second column
 */
DECLSPEC void matrix_swap_columns(matrix_t matrix, int first_column, int second_column);

/*!
 * @brief Returns transposed matrix.
 * Complexity O(1)
 *
 * @param Matrix
 */
DECLSPEC matrix_t matrix_transpose(matrix_t matrix);

/*!
 * @brief Iterates over the keys of the current matrix - first on columns and
 * then on rows.
 * Complexity O(rows*columns)
 *
 * @param Matrix
 * @param Pointer to handling function
 * @param Pointer to context
 */
DECLSPEC void matrix_iterate(matrix_t matrix,
		void key_handler(void *key, void *context), void *context);

#endif /* MATRIX_H_ */
